package com.ruoyi.project.fusion.algorithms;

import com.ruoyi.project.fusion.domain.HumanResourceAggInfo;
import com.ruoyi.project.fusion.domain.HumanResourceScores;
import com.ruoyi.project.fusion.utils.ComputeUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

public class HumanResourceAlgorithm {
    public List<HumanResourceScores> compute(List<HumanResourceAggInfo> aggregatedInfos) {
        List<HumanResourceScores> scoresList = new ArrayList<>();

        // 按照 chainType、scenario、product、event 分组
        Map<List<String>, List<HumanResourceAggInfo>> groupedInfos = aggregatedInfos.stream()
                .collect(Collectors.groupingBy(info -> Arrays.asList(
                        info.getChainType(),
                        info.getScenario(),
                        info.getProduct(),
                        info.getEvent()
                )));

        for (Map.Entry<List<String>, List<HumanResourceAggInfo>> entry : groupedInfos.entrySet()) {
            List<HumanResourceAggInfo> group = entry.getValue();

            // 计算 totalAmount*avgTrainingEffect 和 totalAmount*avgEmployeeSkillLevel
            List<Double> trainingEffectValues = group.stream()
                    .map(info -> info.getTotalAmount() * info.getAvgTrainingEffect())
                    .collect(Collectors.toList());

            List<Double> skillLevelValues = group.stream()
                    .map(info -> info.getTotalAmount() * info.getAvgEmployeeSkillLevel())
                    .collect(Collectors.toList());

            // 归一化数据
            List<Double> normalizedTrainingEffectValues = ComputeUtils.normalizeValues(trainingEffectValues);
            List<Double> normalizedSkillLevelValues = ComputeUtils.normalizeValues(skillLevelValues);

            // 计算标准差
            double trainingEffectStdDev = ComputeUtils.calculateStandardDeviation(normalizedTrainingEffectValues);
            double skillLevelStdDev = ComputeUtils.calculateStandardDeviation(normalizedSkillLevelValues);

            double totalStdDev = trainingEffectStdDev + skillLevelStdDev;
            double trainingEffectWeight = (totalStdDev == 0) ? 0.5 : trainingEffectStdDev / totalStdDev;
            double skillLevelWeight = (totalStdDev == 0) ? 0.5 : skillLevelStdDev / totalStdDev;

            for (int i = 0; i < group.size(); i++) {
                HumanResourceAggInfo info = group.get(i);

                double weightedTrainingEffect = normalizedTrainingEffectValues.get(i) * trainingEffectWeight;
                double weightedSkillLevel = normalizedSkillLevelValues.get(i) * skillLevelWeight;

                float score = (float) (weightedTrainingEffect + weightedSkillLevel);

                HumanResourceScores humanResourceScore = new HumanResourceScores();
                humanResourceScore.setChainType(info.getChainType());
                humanResourceScore.setEnterpriseName(info.getEnterpriseName());
                humanResourceScore.setScenario(info.getScenario());
                humanResourceScore.setProduct(info.getProduct());
                humanResourceScore.setEvent(info.getEvent());
                humanResourceScore.setScore(ComputeUtils.roundToTwoDecimalPlaces(score));

                scoresList.add(humanResourceScore);
            }
        }

        return scoresList;
    }
}
